if (window.Clickoutside === undefined) {
  window.Clickoutside = function () {
    var nodeList = [];
    var ctx = '@@clickoutsideContext';

    var startClick;
    var seed = 0;

    $(document).on('mousedown', function (e) {
      startClick = e;
    });

    $(document).on('mouseup', function (e) {
      for (var i = 0; i < nodeList.length; i++) {
        var node = nodeList[i];
        node[ctx].documentHandler(e, startClick)
      }
    });

    function createDocumentHandler(el, binding, vnode) {
      return function (mouseup = {}, mousedown = {}) {
        if (!vnode ||
          !vnode.context ||
          !mouseup.target ||
          !mousedown.target ||
          el.contains(mouseup.target) ||
          el.contains(mousedown.target) ||
          el === mouseup.target ||
          (vnode.context.popperElm &&
            (vnode.context.popperElm.contains(mouseup.target) ||
              vnode.context.popperElm.contains(mousedown.target)))) return;

        if (binding.expression &&
          el[ctx].methodName &&
          vnode.context[el[ctx].methodName]) {
          vnode.context[el[ctx].methodName](startClick);
        } else {
          el[ctx].bindingFn && el[ctx].bindingFn(startClick);
        }
      };
    }

    return {
      bind(el, binding, vnode) {
        nodeList.push(el);
        var id = seed++;
        el[ctx] = {
          id,
          documentHandler: createDocumentHandler(el, binding, vnode),
          methodName: binding.expression,
          bindingFn: binding.value
        };
      },

      update(el, binding, vnode) {
        el[ctx].documentHandler = createDocumentHandler(el, binding, vnode);
        el[ctx].methodName = binding.expression;
        el[ctx].bindingFn = binding.value;
      },

      unbind(el) {
        var len = nodeList.length;

        for (var i = 0; i < len; i++) {
          if (nodeList[i][ctx].id === el[ctx].id) {
            nodeList.splice(i, 1);
            break;
          }
        }
        delete el[ctx];
      }
    };
  }();
}
